package com.haiyou.data.common.accessor;

import java.io.Serializable;
import java.util.Objects;

import org.apache.commons.lang3.Validate;

import com.haiyou.common.entity.Entity;
import com.haiyou.common.spring.component.LifecycleableComponent;
import com.haiyou.common.util.object.ClassUtils;
import com.haiyou.data.common.accessor.IdManager.KeyGenerator;
import com.haiyou.data.common.accessor.IdManager.KeyMultiplexer;
import com.haiyou.data.common.accessor.IdManager.KeyRecycler;


public abstract class AbstractAccessor<K extends Serializable & Comparable<K>, V extends Entity<K>>
		implements Accessor<K, V>, LifecycleableComponent {

	protected Class<?> initClass;
	protected Class<K> keyClass;
	protected Class<V> valueClass;

	protected KeyGenerator<K> keyGenerator;
	protected KeyRecycler<K> keyRecycler;
	protected KeyMultiplexer<K> keyMultiplexer;

	@Override
	public Class<K> getKeyClass() {
		if (keyClass == null) {
			keyClass = getKeyClass(this.getClass());
			Objects.requireNonNull(keyClass, this.getClass().getName());
		}
		return keyClass;
	}

	private Class<K> getKeyClass(Class<?> clazz) {
		Class<?>[] cls = ClassUtils.getTypeArguments(clazz);
		Class<K> clz = (Class<K>) (cls.length == 2 ? cls[0] : null);
		if (clz != null)
			return clz;
		return getKeyClass(clazz.getSuperclass());
	}

	@Override
	public Class<V> getValueClass() {
		if (valueClass == null) {
			Class<?>[] cls = ClassUtils.getTypeArguments(this.getClass());
			valueClass = (Class<V>) (cls.length == 2 ? cls[1] : cls[0]);
			Objects.requireNonNull(valueClass, this.getClass().getName());
		}
		return valueClass;
	}

	@Override
	public void init() {
		keyClass = getKeyClass();
		valueClass = getValueClass();
		IdManager<K> idManager = getIdManager();
		if (idManager != null) {
			keyGenerator = idManager.getKeyGenerator();
			keyRecycler = idManager.getKeyRecycler();
			keyMultiplexer = idManager.getKeyMultiplexer();
		}
		
		AbstractAccessor<K, V> old = (AbstractAccessor<K, V>) pool.putIfAbsent(valueClass, this);
		Validate.isTrue(old == null, "重复注册[%s]数据存储器[%s],old=%s", valueClass, this, old);
	}

	@Override
	public void destory() {

	}

	@Override
	public K generateKey() {
		K id = null;
		if (keyMultiplexer != null) {
			id = keyMultiplexer.reuse();
			if (id != null)
				return id;
		}
		if (keyGenerator != null) {
			id = keyGenerator.generate();
			if (id != null)
				return id;
		}
		return null;
	}

	@Override
	public int getOrder() {
		return accessor_order;
	}
	
	

}
